#include <iostream>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <strings.h>
#include <string.h>
#include <signal.h>
#include <string>
#include <errno.h>
#include "Translate.hpp"
#include "ThreadBool.hpp"
#include "Task.hpp"
#include "Deamon.hpp"
#include "log.hpp"

using namespace std;
const string defaultip = "0.0.0.0";

uint16_t defaultport = 8899;
const int backlog = 5; // 监听的连接个数
                       // #define SIZE 1204   日志文件里面有SIZE=1024;

Log lg; // 日志
Translation_ T;

class Server;

class ThreadData
{
public:
    ThreadData(int sock, uint16_t port, string ip, Server *svr)
        : Sock(sock), Port(port), IP(ip), svr_(svr)
    {
    }
    int Sock;
    uint16_t Port;
    string IP;
    Server *svr_;
};

enum errnum
{
    UsageError = 1,
    SockError,
    BindError,
    ListenError
};

class Server
{
public:
    Server(uint16_t port = defaultport, string ip = defaultip)
        : port_(port), ip_(ip)
    {
    }
    void Init()
    {
        struct sockaddr_in local;
        bzero(&local, sizeof(local));

        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        inet_aton(ip_.c_str(), &(local.sin_addr));
        socklen_t len = sizeof(local);

        listensock_ = socket(AF_INET, SOCK_STREAM, 0);
        if (listensock_ < 0)
        {
            lg("fatal", "socket create error erron:%d errstring:%d", errno, strerror(errno));
            exit(SockError);
        }

        lg("info", "socket create success");

        int opt = 1;
        setsockopt(listensock_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)); // 防止偶发性的服务器无法进行立即重启(tcp协议的时候再说)

        if (bind(listensock_, (struct sockaddr *)&(local), len) < 0) // 绑定端口
        {
            lg("fatal", "bind fail error erron:%d errstring:%d", errno, strerror(errno));
            exit(BindError);
        }
        lg("info", "bind create success");

        if (listen(listensock_, backlog) < 0) // 设置为监听状态
        {
            lg("fatal", "listen fail error erron:%d errstring:%d", errno, strerror(errno));
            exit(ListenError);
        }
        lg("info", "listen create success");
    }

    // void handle(int sig)
    // {
    //    int ret=waitpid(-1,nullptr,0);
    // }

    // static void *Threadrun(void *args)
    // {
    //     pthread_detach(pthread_self());
    //     ThreadData *s = static_cast<ThreadData *>(args);
    //     s->svr_->Run(s->Sock, s->Port, s->IP);
    //     delete s;
    // }

    void start()
    {
        // signal(SIGCHLD,handle);//根据信号处理子进程的退出。
        ThreadBool<Task>::GetInstance()->start();
        while (true)
        {
            struct sockaddr_in client;
            memset(&client, 0, sizeof(client));
            socklen_t len = sizeof(client);

            int socket_ = accept(listensock_, (struct sockaddr *)&client, &len); // 接受连接请求
            // 这里才是真正的用于传输的套接字端口。
            uint16_t clientport = ntohs(client.sin_port); // client的信息
            string clientip = inet_ntoa(client.sin_addr);

            lg("info", "get a new link..., sockfd: %d, client ip: %s, client port: %d", socket_, clientip.c_str(), clientport);

            // int pid=fork();
            // if (pid>0)
            // {
            //     close(listensock_); // 关闭父进程的listensock_端口,保障自己只做任务。
            //     Run(socket_, clientport, clientip);
            //     close(socket_);//关闭自己的套接字,
            //     exit(0);  //不在向下执行
            // }
            // close(socket_);//关闭父进程的套接字
            // int ret = waitpid(pid, nullptr, 0);//如果采用的是阻塞等待子进程退出的话，依然达不到父子进程分离的效果
            // //1 采用孙子进程，让子进程提前退出，孙子变孤儿有操作系统回收。
            // //2 采用信号方法，收取17号信号，在调用waitpid父进程处理,能达到父进程非阻塞等待回收的效果。

            // if(fork()==0)  //子进程是0
            // {
            //     close(listensock_);
            //     if(fork()>0)
            //     {
            //         close(socket_);
            //         exit(0);//儿子进程退出
            //     }
            //     Run(socket_, clientport, clientip);
            //     close(socket_);
            //     exit(0);
            // }
            // close(socket_);

            // ThreadData *t = new ThreadData(socket_, clientport, clientip, this);
            // pthread_t tid;
            // pthread_create(&tid, nullptr, Threadrun, t);

            Task t(socket_, clientport, clientip);
            ThreadBool<Task>::GetInstance()->Push(t);
        }
    }

    // void Run(int sock, uint16_t &port, string &ip)
    // {
    //     char buffer[SIZE];
    //     while (true)
    //     {
    //         int n = read(sock, buffer, SIZE - 1);
    //         if (n > 0)
    //         {
    //             buffer[n] = 0; // 添加 '\0'
    //             string temp = buffer;
    //             cout << "TCP get a message:" << buffer << endl;
    //             string info = "tcpserver echo#:" + temp;
    //             write(sock, info.c_str(), info.size());
    //         }
    //         else if (n == 0)
    //         {
    //             lg("info", "%s:%d quit, server close sockfd: %d", ip.c_str(), port, sock);
    //             break;
    //         }
    //         else
    //         {
    //             lg("Warning", "read error, sockfd: %d, client ip: %s, client port: %d", sock, ip.c_str(), port);
    //             break;
    //         }
    //     }
    // }

private: // 服务器自己的东西
    int listensock_;
    uint16_t port_;
    string ip_;
};